Repository navigation
Conversation
* fix: the runner and the monitor read their non-blocking socket with read_exact: when a frame arrived in two parts, its length was consumed then dropped on WouldBlock, the next read took the payload as a length, and dosr failed after the command ran with "invalid backchannel message size: 0 bytes" or an rkyv error, then exited 1; with a terminal on a machine with one CPU, it happened on nearly every command (since c524ead, 4.0.2) * fix: the backchannel keeps the bytes of the frame being read until it is complete, and reads no further than that frame, so that poll still reports the next one * fix: a frame is written at once, and a full non-blocking socket is waited for instead of cutting the frame * fix: the monitor ignores WouldBlock on its backchannel instead of leaving its event loop * tests: a frame split at every byte, written byte by byte, two frames in the socket, and a frame sent on a full socket Co-Authored-By: Claude
…er's terminal * tests: a pty follower that is not the controlling terminal is a terminal, but is_terminal_for_pgrp refuses it, so the runner gives it to the command as it is instead of proxying it or setting it to raw mode (sudo-rs #1377, #1380) Co-Authored-By: Claude
…g killed * fix: when the command was stopped (^Z, SIGSTOP, SIGTTIN, SIGTTOU), the monitor reported an error, dosr exited, and the monitor then killed the stopped command with SIGKILL: ^Z on `dosr vim` lost the editor and its unsaved work * feat: the monitor reports the stop with its signal, and keeps the process group that had the pty; dosr gives the terminal back in cooked mode and stops its job with the same signal, so that the shell sees a stopped job * feat: once dosr is continued (fg or bg), it sets the terminal up again, and the monitor resumes the command with the pty in its foreground when dosr is in the foreground of the user's terminal, in the background otherwise * fix: a command stopped by SIGTTIN or SIGTTOU while dosr is in the foreground is resumed at once, whether the terminal was already raw or not (sudo-rs #1598) * tests: the suspend messages round trip, and a signal action changed while suspending is put back Co-Authored-By: Claude
… terminal at the same time * fix: with `dosr a | dosr b`, both prompts read /dev/tty at once, each one got part of the keystrokes and both authentications failed; dosr now holds an exclusive flock on its terminal while it authenticates, and the other one waits, then checks its timestamp once it gets the lock (sudo-rs #1650, #1651) * fix: no lock with -S (the password comes from stdin) or when authentication is skipped; without a terminal, or when the lock cannot be taken, dosr goes on without it * tests: the lock is exclusive between two opens of the terminal and released on drop, and there is none without a terminal Co-Authored-By: Claude
…e SIGKILL * fix: when dosr has to stop a command itself (SIGALRM, the monitor done while the command runs, no job to suspend), it sent SIGKILL at once, so a package manager or a database could not remove its lock or finish a write * fix: terminate_process sends SIGHUP, SIGTERM, then SIGKILL two seconds later, to the command's process group when the monitor is done or the suspension fails, to the command alone for SIGALRM, like sudo's terminate_command * fix: terminate_process refuses a pid of 0 or less, which would signal dosr's own group or every process * tests: a command that handles the signals cleans up and exits, one that ignores them is killed after the delay Co-Authored-By: Claude
* chore: the next release is 4.2.0, since it adds the password retries (a new policy option) * feat: migration edge from 4.1.0 to 4.2.0, without any change for now; every released version needs one, otherwise its documents cannot be migrated * tests: a 4.1.0 document goes up to 4.2.0 and back down unchanged, but for its version Co-Authored-By: Claude
…ore fields follow * fix: "-00:00:01" was read as one second, since "-00" parses as 0 and the negative check missed it; "+00:00:01" and "00:05:00:junk" were accepted too, the fourth field ignored * fix: a duration is exactly three fields of digits, hh:mm:ss * tests: signs on a zero field, a plus sign, extra, empty and missing fields are refused Co-Authored-By: Claude
…er a wrong one
* feat: a wrong password (PAM_AUTH_ERR) is asked again, after a delay, with "Sorry, try again."; any other PAM error, such as the end of the input or an unknown user, stops at once, without delay
* feat: the tries and the delay are build-time defaults, RAR_PASSWORD_TRIES (3) and RAR_PASSWORD_DELAY (00:00:05), and a policy option at every level, "password": {"tries": 3, "delay": "00:00:05"}, each field inherited on its own
* feat: tries is 1 to 255, 0 is refused: it would never let anyone in, or never stop asking (sudo-rs #1309); a build value out of range stops the build
* feat: the downgrade to 4.1.0 removes the password option, which 4.1.0 does not know
* tests: the option's format and defaults, its CBOR round trip, the inheritance of each field, the migrations, and the retries until success, up to the last try, and stopping on another error
Co-Authored-By: Claude
* fix: a PAM module may change PAM_USER during the transaction (pam_get_item(3)), and dosr went on with the session of another user than the one it authenticated; it now checks PAM_USER after the account management, with or without password, and after opening the session, and refuses when it changed or cannot be read * tests: the comparison of the PAM user; the PAM tests of start_session pass the checks Co-Authored-By: Claude
…he env filter of the policy * feat: dosr reads the PAM environment once the session is open (pam_getenvlist(3), set by pam_env or pam_systemd) and adds the variables that the env options of the task keep, as for the variables of the user: keep and check lists in delete mode, delete and check lists in keep mode, never a shell function; pam_env may read a file that the user writes (~/.pam_environment with user_readenv=1) * feat: a variable that the command already has is left as it is: the kept variables of the user, those set by dosr (PATH, HOME, USER, RAR_*, SUDO_*) and the set list take precedence * feat: a PAM variable that is not UTF-8, or has no name, is left out * chore: rootasrole-core gets EnvFilter, the filter of ResolvedEnv owned so that it outlives the policy; both use the same rule * tests: the owned filter decides as the policy's, the precedence, the filter of a task with and without dosr -E, and the PAM environment read from a transaction Co-Authored-By: Claude
…etries * tests: the variables that pam_env sets reach the command through the env filter of the task, and never replace PATH nor a variable of the user that the task keeps; pam_env is added to the PAM service of dosr for the check, then the service is restored, since Debian's common-* files do not run it * tests: with -S, three wrong passwords are refused, two wrong ones then the right one are accepted after two "Sorry, try again."; the timestamp cookie and the pam_faillock counter (Arch) are cleared around the check Co-Authored-By: Claude
* fix: with the ppid scope (and the tty scope without a terminal), a cookie served any process of the same parent, even in another session after setsid(2); the record now keeps the session id, like sudo; only the id, since the session leader may be gone while the session lives on * fix: the cookies of 4.1.0 have no session and are no longer reused: the password is asked once after the upgrade; after a downgrade, 4.1.0 reads the new cookies and ignores the session * tests: a cookie from another session is refused, the record holds the session of dosr, a 4.1.0 cookie is not reused, 4.1.0 reads a new cookie Co-Authored-By: Claude
* fix: Rust ignores SIGPIPE, so a write to a pipe that nobody reads (dosr --help | true, dosr -i | head) fails with EPIPE, and println! and eprintln! panic on it; dosr ended with exit code 101, and a message of a PAM module printed from the conversation, a callback of libpam, would abort the process * fix: rootasrole-core exports println_ignore_io_error!, print_ignore_io_error! and eprintln_ignore_io_error!, which ignore write errors; dosr and chsr use them outside the tests * chore: outside the tests, the crate roots of rootasrole-core, dosr and chsr shadow println!, print!, eprintln! and eprint! with a compile_error!, so that a new use does not build * tests: dosr --help and --version with stdout on a closed pipe exit 0 without a panic Co-Authored-By: Claude
* fix: a relative directory of the path option (".", "", "bin") was kept in every mode; it is the working directory of the command, which the user chooses: it is now kept only in keep-unsafe mode, like the relative directories of the user, and logged when left out
* fix: with no directory left (delete mode with "add": []), dosr set PATH to the empty string, which shells and execvp(3) search as the working directory; the command now has no PATH, and its own default applies; the set list of the policy can still give one
* fix: a PATH set by PAM never fills an absent PATH
* tests: relative directories of the policy and of the user, the empty one included, in each mode; no PATH without directories, even when the user's PATH is kept by name or PAM sets one; a task without any directory
Co-Authored-By: Claude
* fix: the policy files that chsr opened for writing were created with the mode of the umask, 0644 with the usual 022: the policy was readable by every user, and a umask of 000 made it writable by them, so that dosr refused it; they are now created 0600, like the files of the installers * tests: a new root file or policy file is never more than 0600; saving rewrites the file in place and keeps its owner and mode Co-Authored-By: Claude
…sion denied * fix: when dosr runs without the capabilities it needs (setpcap, setuid, and dac_read_search or dac_override), reading the policy failed and the user only saw "Permission denied", as if the policy refused the command; dosr now prints why after the error, and logs it * fix: three causes are told apart: no_new_privs (the file capabilities are ignored: a service with NoNewPrivileges=yes, a container, setpriv, or a command that dosr runs with "root": "user", the usual nested session), a bounding set that lacks them (CapabilityBoundingSet=, a container, a command run with a strict bounding set), or a dosr file without capabilities or on a nosuid file system * tests: each cause, and one DAC capability being enough Co-Authored-By: Claude
… startup errors * fix: chsr created its temporary folder and read the policy before parsing its arguments, both with expect: without the privileges to read the policy, even chsr --help ended in a panic; --help and a usage error are now handled first, without the policy * fix: a failure to create the temporary folder or to read the policy is an error message on stderr and in the log, with a failure exit code * fix: a non-UTF-8 argument is refused instead of panicking in std::env::args() * tests: which arguments need the policy; chsr --help without privileges prints the usage and exits 0 Co-Authored-By: Claude
* chore: packages are made by Debian (debcargo-conf) and the AUR (dosr), not upstream (decided on 2026-10-19): xtask deploy, which could not build the deb and rpm packages anymore since their metadata left Cargo.toml, is removed with its feature * chore: resources/arch/PKGBUILD and rootasrole.install, resources/rh/postinst.sh and prerm.sh, and the Vagrantfiles of tests/capable are removed; the PAM service files of resources/arch and resources/rh stay, since cargo xtask install and uninstall use them Co-Authored-By: Claude
* tests: json! serializes an interpolated value by reference, so the commands of test_commands_without_arguments_up_and_down need no clone; only clippy on the whole workspace lints the tests of rootasrole-core Co-Authored-By: Claude
* fix: a policy in keep mode, or dosr -E where allowed, passes the user's TMPDIR to chsr: its 0700 folder was then created in a directory that the user may own, where the user can rename it and put another one in its place; /tmp is sticky (decided by the maintainer on 2026-10-23) Co-Authored-By: Claude
… of duties * fix: an actor written by name whose lookup failed (a directory service that does not answer, a group whose members take more than the 1 MiB that nix allows for getgrnam_r) was taken as a name that nobody has: the user did not hold the role, and the SSD plugin let the user take a role that excludes it * fix: dosr now tells a failed lookup from an unknown name: the actor still never matches, the failure is logged, and every role of the policy file that has an ssd is disabled, since its separation of duties cannot be checked (decided by the maintainer on 2026-10-23); SSD only names roles of the same file * feat: rootasrole-core gets DUserType::try_fetch_id and DGroupType::try_fetch_id, fetch_id keeps its meaning * tests: a failed lookup never matches and is reported, even with another matching actor; the roles with ssd are disabled whatever role the failed lookup belongs to, the others are not, through the hierarchy too Co-Authored-By: Claude
* tests: e2e.sh adds a role with an ssd and a role held through a group written by name; once the group has 120000 members, more than the 1 MiB of the lookups of dosr, getgrnam_r fails with ERANGE and the role with the ssd is refused; /etc/group and /etc/gshadow are restored, at the end of the check and in the cleanup Co-Authored-By: Claude
…or panicking * fix: chsr options timeout set --duration read a field that does not fit as 0 and ended in a panic when adding the fields overflowed: 153722867280912930:59:59 gave 00:59:59; a duration is now computed with checked arithmetic, and one that does not fit is an error * tests: the forms ss, mm:ss and hh:mm:ss, and durations too long, alone and through the timeout command Co-Authored-By: Claude
* feat: chsr [role R [task T]] options password set [--tries N] [--delay hh:mm:ss] and unset [--tries] [--delay], and options show password * feat: set changes the fields given and keeps the others; unset removes the fields named, then the option once nothing is left in it; the fields that this version does not know are kept * feat: tries is 1 to 255, a delay that does not fit is refused, and set without a value is an error * tests: each level, field by field, the unknown fields, the refused values, the usage, and the saved file read back Co-Authored-By: Claude
… task * fix: a role or task without options got Opt::default(), which holds every built-in default (env and path lists, bounding, authentication, timeout, password...): chsr role R options root user wrote them all at the role, where its lists replaced those of the upper levels; the options are now created empty, at their level * fix: whitelist, blacklist, checklist and setlist of path and env worked on a temporary when the level had no path or env option: chsr reported a success and saved nothing; they now edit the option, and removing from a list that the level does not define changes nothing * tests: the options of a new role and task, and list edits on a level without the option, read back from the saved file Co-Authored-By: Claude
* fix: set and unset started from an empty timeout: set --type tty dropped the duration and the max usage, unset --duration dropped the type, the max usage and the unknown fields, and left an empty object * fix: set changes the fields given, unset removes the fields named, then the option once nothing is left in it; set without a value is an error * tests: chsr options timeout, field by field, with an unknown field and a level without the option, read back from the saved file Co-Authored-By: Claude
…no others * fix: the grammar of chsr required two characters (o env whitelist add A was refused), refused the * of patterns (LC_* could not be added), but accepted - and non-ASCII letters, which EnvKey refuses: o env whitelist add MY-VAR panicked; a key now follows is_valid_env_pattern, and is built with EnvKey::new, an error instead of a panic * fix: the names of the set list are variable names, a * is refused there as the policy does * fix: a refused name says what is expected instead of "unknown rule" * tests: one letter, patterns, and the names that the policy refuses Co-Authored-By: Claude
…nics into errors * fix: options show only filtered at the task level: at the global and role levels it printed every option, the whole policy for the global level; it now shows the resolved options of the level, or the one asked for * fix: options show can name authentication (auth), execinfo (info), umask (mask), workdir and password; cmd and cred, which are not options, panicked in an unreachable! and are refused * fix: chsr role R task T purge on a task that does not exist panicked; it and the other unreachable! and expect of chsr outside the tests are errors * tests: every option name at every level, missing roles and tasks, and the purges that the grammar accepts Co-Authored-By: Claude
…e policy unreadable
* fix: STimeout.duration has a deserialize_with but no default, so serde required it although it is an Option: a policy with "timeout": {"type": "tty"} could not be read, neither by chsr nor by dosr, which refused every request; chsr itself wrote such timeouts (options timeout set --type on a level without a timeout)
* tests: every field of the timeout may be left out; the chsr tests check that the policy they save parses again
Co-Authored-By: Claude
…ge when it saves * fix: SPathOptions, SWorkdirSet, SSetuidSet, SettingsContent and RemoteStorageSettings had no extra_fields, unlike the other objects of the policy: a field written by a newer version disappeared at the next chsr command; they keep them now, the serializer of SSetuidSet in JSON and CBOR * tests: every unknown field of a policy survives a chsr save; the sets and the storage settings round-trip, CBOR included; cred.capabilities and cred.setgid still refuse unknown fields Co-Authored-By: Claude
…ents, whatever its alternations * fix: ^start|stop$ is ^start or stop$ for the regex crate, so a rule allowed any arguments starting with start or ending with stop; dosr now compiles ^(?:body)$, so that it allows start or stop alone; a group, a character class and an escaped bar keep their meaning, and an escaped final dollar sign stays in the body * chore: rootasrole-core gets regex_body, anchored_regex and has_top_level_alternation in database::command, which tells a bar outside of any group and class, escapes included * feat: the downgrade to 4.1.0 writes a top-level alternation ^(?:start|stop)$, in lists and selectors and with the short keys, so that 4.1.0 allows no more than 4.2.0; the upgrade leaves the rules as written, since they now allow less (decided by the maintainer) * tests: ^start|stop$ allows start and stop, not start anything nor please stop, and the test fails without the anchoring; groups, classes and escapes; the body and its anchored form; the downgrade and the upgrade Co-Authored-By: Claude
* tests: ^one|two$ allows echo one, and refuses echo one more and echo say two Co-Authored-By: Claude
…cides as the chapter says * tests: the policy under "The complete WebOps policy" of book/src/configuration.md is migrated and read by rootasrole-core, then dosr decides with it, the current user in place of the team except sys-admin: the logs are read with tail, less and journalctl, the path traversal and the pager of systemctl are refused, caddy-service manages caddy and nothing else, alice's escape with install is refused, web-push publishes where www-data exists, and the tasks of sys-admin are not held * tests: skipped when the book is not in the source tree (the crate and the Debian sources leave it out), so until the docs are merged into dev; checked against the current page, and the test fails when the rule of tail lets a path traversal through Co-Authored-By: Claude
…line * fix: the services of Red Hat, openSUSE and Arch had no final newline, so a line appended to /etc/pam.d/dosr was glued to the last one (session include system-authsession optional pam_env.so …): the line was lost, and the include broken; found by the e2e check of pam_env on Arch * tests: every PAM service built into xtask ends with a newline Co-Authored-By: Claude
* tests: archlinux/archlinux publishes no box for libvirt anymore; generic/arch does, and the Vagrantfile says how to upgrade it the first time, since vagrant installs rsync without upgrading the system and breaks it Co-Authored-By: Claude
…aller by default
* feat: "options": {"tty": {"owner": "caller"|"target"}} at every level, inherited like the others; caller, the default, keeps the behaviour of 4.1.0: the terminal stays with the user who runs dosr, so the processes of the target account cannot open it, but a program that reopens its terminal by its name (pinentry through GPG_TTY) fails; target gives it to the user that the command runs as, like sudo and sudo-rs since 0.2.11, at the cost of letting the other processes of that account open it while the command runs (#51)
* feat: with target, and only for a command run as another user, dosr changes the owner of the pty with fchown on its descriptor, keeping its group and mode, with CAP_CHOWN raised for that call only; sudo-rs changes it by its path (src/exec/use_pty/parent.rs, get_pty); a failure stops before the command starts
* feat: rootasrole-exec gets PtyFollower::set_owner and runner::run_with_pty_setup, which lets the caller prepare the pty before the command starts; run and run_with_pty keep their signature; a failed setup gives the caller back its signal mask
* feat: the downgrade to 4.1.0 removes the tty option, which 4.1.0 does not know: the terminal stays with the caller
* fix: a doc comment of path_only in the migrations was above another function
* tests: the option's format, CBOR round trip, default and inheritance, its migrations, the owner chosen by dosr, set_owner, and a failed setup that stops before the command and restores the signal mask
Co-Authored-By: Claude
* feat: chsr [role R [task T]] options tty owner target|caller|unset, and options show tty * feat: unset removes the owner, then the option once nothing is left in it; the fields that this version does not know are kept * feat: the help lists the tty option, and a wrong command shows its usage; t stays the alias of timeout * tests: each level, the unknown fields, the refused values, timeout through its alias, the usage, and the saved file read back Co-Authored-By: Claude
…n as another user
* tests: a task run as nobody through script sees a terminal of the caller that it cannot reopen by its name, and with "tty": {"owner": "target"} a terminal of nobody that it reopens, as pinentry does through GPG_TTY
* tests: script gets no input, otherwise it copies into the terminal what is left on the input of the provisioner
* tests: 24 checks pass on the Debian and Arch machines
Co-Authored-By: Claude
…_OWNER * feat: RAR_TTY_OWNER in the [env] of .cargo/config.toml, read with env! like the defaults of the other options; caller upstream, so the default exposes nothing more than 4.1.0, and a build that wants the behaviour of sudo sets target * feat: TtyOwner::const_parse; a value that is neither caller nor target stops the build; TtyOwner::default() is the build-time value * chore: the Debian copies of [env] need RAR_TTY_OWNER, like RAR_PASSWORD_TRIES and RAR_PASSWORD_DELAY * tests: the shipped value is caller, the policy and dosr fall back to it Co-Authored-By: Claude
Note: The content of this document is based on human writing. However, the content is cross-checked with the code behavior by AI. Also we both verified edge cases of the taken example for ensuring correctness between code and docs. See recent dozens of fix commits about it.
…ps exist * tests: the GitHub Actions container (xd009642/tarpaulin, Debian without systemd) has no systemd-journal group, so dosr leaves read-logs out, as a task whose group does not exist (68ea667), and test_the_policy_of_the_book failed on its first decision; the groups are read from the policy of the book, and without them the task must be left out * tests: checked with the page of the docs branch as is, and with systemd-journal replaced by a group that does not exist, where the previous version of the test fails like the CI Co-Authored-By: Claude
* fix: the merge of docs into dev kept both help entries of -S and -K, the ones of docs: update usage (b8c3c45) and the ones of 4267132; the entries of 4267132 stay, since they say what dosr does: -K removes the cookies before authentication, not after it * tests: each option of dosr is listed once in its help; the test fails on the help of 6859639 Co-Authored-By: Claude
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #111 +/- ##
==========================================
+ Coverage 74.19% 77.00% +2.80%
==========================================
Files 60 62 +2
Lines 6686 7561 +875
==========================================
+ Hits 4961 5822 +861
- Misses 1725 1739 +14
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
* tests: cargo test --release --all-features --lib -- --ignored --nocapture finder::tests::perf prints the time of a decision with a policy of 1 and of 10 000 tasks, where only the last task allows the command (the policies of perf/confgen), and the cost of one task; no time is asserted, the machine decides * tests: a command given by its path, with root named in each task (CBOR and JSON), root given by its id, the command searched in the PATH, and commands written as patterns; one indicator at a time, each in its own folder * tests: on 4.2.0 (VM, release), one task costs 35 µs with root named (351 ms for 10 000 tasks), 12.8 µs with root by id, 76 µs for a command in the PATH (764 ms), 38 µs with patterns; sudo costs about 3 µs per rule on the same machine Co-Authored-By: Claude
… as a glob
* perf: match_single_path compiled every path of the policy that differed from the command into a globset matcher, about 10 µs each, for each command of each task: a path without *, ?, [, { or \ only matches the path written the same way, which the comparison before already found
* perf: \ still makes a pattern, since globset reads it as an escape, so these paths keep their meaning
* tests: the characters that make a pattern, an escaped *, and paths that differ by a suffix
* perf: one task costs 23 µs instead of 35 µs with root named, 2.6 µs instead of 12.8 µs with root by id (the indicators of finder::tests::perf)
Co-Authored-By: Claude
* perf: the score of each task checks whether its target is root, so a policy that names root (or any user or group) looked the name up for each task, through NSS: with systemd-userdb (group: files [SUCCESS=merge] systemd on Arch), about 20 µs per task * perf: DUserType and DGroupType keep the ids that a thread looked up, a name that nobody has included; a failed lookup is not kept, so that the separation of duties still sees it (09d0ea1) * tests: a name is looked up once, a name that nobody has is kept, an id is never looked up * perf: with the previous commit, one task costs 3.1 µs instead of 35 µs with root named (31 ms instead of 351 ms for 10 000 tasks), 13 µs instead of 76 µs for a command in the PATH, 16 µs instead of 38 µs with patterns Co-Authored-By: Claude
* fix: start_session updated the cookie after every session, and update_cookie creates one when none is valid: a task with authentication skip gave a cookie, so a later task that requires the password, with the same type of timeout (ppid by default), ran without it, from the same parent; software in the account of the user could run the first task to get past the second; v4.1.0 does the same * fix: timeout::record_authentication creates or extends the cookie only when the authentication was not skipped, like sudo-rs, which records an authentication only after it (src/sudo/pipeline.rs, auth_and_update_record_file) * perf: with authentication skip, dosr no longer locks, reads and rewrites the cookie file * tests: a skipped authentication neither creates nor extends a cookie, and the test fails without the fix; tests/vagrant/e2e.sh: a task that requires the password, run from the same shell after a task that skips it, refuses wrong passwords Co-Authored-By: Claude
* perf: make_cred looked up the name of every group of the caller, through NSS, at each run: with systemd-userdb (group: files [SUCCESS=merge] systemd on Arch), about 0.5 ms per group, 2.2 ms for a user of 4 groups; the decision compares the gids of the policy with the gids of the caller (finder/de/roles.rs), and the logs and -i show the groups of the command, so the names were never used * perf: measured with a timing probe on the test VM (median of 200 runs, one task, authentication skip): the credentials take 0.1 ms instead of 2.2 ms; with the previous commit, a run takes 10.1 ms instead of 13.1 ms with 4.2.0 (hyperfine, 300 runs) * tests: make_cred keeps the ids of the groups, never looked up Co-Authored-By: Claude
…its PATH only when needed * perf: the options of each task (its environment entries, -E, the working directory, -i), its score and the notification of the plugins were computed before its commands were compared, for every task of the policy; most tasks do not allow the command, and a task that does not returned false either way, so they are now computed for the tasks that allow it * perf: the PATH of a task (an IndexSet per task) is only resolved when the command is typed by its name, or when a rule of the task resolves the command itself (**, the all default, a complex command for a plugin); the task that wins gets its PATH as before * perf: BestTaskSettingsFound is sent for the tasks that allow the command, which no plugin listens to * perf: one task costs 2.1 µs instead of 3.1 µs with root named, 1.5 µs instead of 2.7 µs with root by id (finder::tests::perf), with the next commit Co-Authored-By: Claude
* perf: every command of every task went through shell_words::split and was copied into a vector of strings; a command without space, quote or backslash is a path alone, matched as it is: like a command line of one word, it allows the command without arguments * perf: with the previous commit, one task costs 2.1 µs instead of 3.1 µs with root named (finder::tests::perf) Co-Authored-By: Claude
* perf: a command typed by its name was searched in the PATH for each command of each task, with a stat per directory, though most tasks share their PATH; the searches are kept while find_best_exec_settings runs, by PATH and command name, and dropped at its end, so that another decision, or a direct call (tests, fuzzing, plugins), sees the files as they are then; the candidates and their order are the same * perf: one task costs 3.0 µs instead of 13 µs for a command typed by its name (finder::tests::perf) Co-Authored-By: Claude
…ompiled
* perf: each pattern of the policy was compiled into a globset matcher (about 10 µs) for each command typed; the characters before the first special one (*, ?, [, {, \) are matched as they are, so a command path that does not start with them cannot match, and the pattern is not compiled
* tests: the literal start of patterns, and a pattern whose start differs
* perf: one task costs 2.0 µs instead of 13 µs with patterns that start differently (finder::tests::perf); a pattern that starts like the command, such as /usr/bin/*, is still compiled
Co-Authored-By: Claude
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Another bugfix done in collaboration with Claude. I'll write the changelog afterward